package com.cabal.socket;

import com.cabal.auth.dao.CabalAuthMapper;
import com.cabal.auth.vo.CabalAuthVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{clientId}")
public class KilledWebSocketServer {

    private Session session;

    private String clientId;

    private static Map<String, KilledWebSocketServer> clients = new ConcurrentHashMap<String, KilledWebSocketServer>();

    private static String ON_CLOSE_KEY = "ON_CLOSE_KEY_";

    private static CabalAuthMapper cabalAuthMapper;

    @Autowired
    public void setCabalAuthMapper(CabalAuthMapper cabalAuthMapper){
        this.cabalAuthMapper = cabalAuthMapper;
    }

    private static StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate){
        this.stringRedisTemplate = stringRedisTemplate;
    }

    // 连接时执行
    @OnOpen
    public void onOpen(@PathParam("clientId") String clientId, Session session) throws IOException {
        this.session = session;
        this.clientId = clientId;
        clients.put(clientId, this);
        log.info("客户端连接>>>>{}", clientId);
        //log.info("客户端IP地址>>>>" + getClientIpAddress(session));
    }

    // 关闭时执行
    @OnClose
    public void onClose(@PathParam("clientId") String clientId, Session session) {
        clients.remove(clientId);
        stringRedisTemplate.opsForValue().set(ON_CLOSE_KEY.concat(clientId), stringRedisTemplate.opsForValue().get(clientId), Integer.valueOf(300), TimeUnit.SECONDS);
        log.info("客户端{}-{}连接关闭，移除客户端", stringRedisTemplate.opsForValue().get(clientId), clientId);
        /*Set<String> allKeys = stringRedisTemplate.keys(ON_CLOSE_KEY + "*");
        if(allKeys.size() >= 8) {
            log.info("有人捣乱开始执行查询当前主地图在线人员...");
            List<CabalAuthVo> cabalAuthVoList = cabalAuthMapper.searchOnlineUserListWithMap();
            for(CabalAuthVo cabalAuthVo : cabalAuthVoList) {
                Integer worldIdx = cabalAuthVo.getWorldIdx();
                Integer userNum = cabalAuthVo.getUserNum();
                CabalAuthVo accountVo = cabalAuthMapper.getCabalAuthVoByUserNum(userNum);
                log.info("有人捣乱当前主地图在线人员{}-{}-{}-{}", userNum, accountVo.getUserId(), clientId, worldIdx);
            }
        }*/
    }

    // 收到消息时执行
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        log.info("收到客户端{}的消息: {}", getClientIpAddress(session), message);
    }

    // 连接错误时执行
    @OnError
    public void onError(@PathParam("clientId") String clientId, Throwable error, Session session) {
        log.info("用户id为：" + clientId + "的连接出现错误，等待客户端重连");
    }

    /**
     * 发送消息给某个客户端
     * @param message
     * @param To
     * @throws IOException
     */
    public static void sendMessageTo(String message, String To) throws IOException {
        for (KilledWebSocketServer item : clients.values()) {
            if (item.clientId.equals(To))
                item.session.getAsyncRemote().sendText(message);
        }
    }

    /**
     * 发送消息给某些客户端
     * @param message
     * @param To
     * @throws IOException
     */
    public static void sendMessageToSomeone(String message, String To) throws IOException {
        for (KilledWebSocketServer item : clients.values()) {
            if (item.clientId.startsWith(To))
                item.session.getAsyncRemote().sendText(message);
        }
    }

    /**
     * 发送消息给所有客户端
     * @param message
     * @throws IOException
     */
    public static void sendMessageAll(String message)  {
        try {
            for (KilledWebSocketServer item : clients.values()) {
                if(item.session.isOpen()) {
                    item.session.getAsyncRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            log.error("向客户端发送消息出错", e);
        }
    }

    /**
     * 发送消息
     * @param session
     * @param message
     * @throws IOException
     */
    private void sendMessage(Session session,String message) throws IOException{
        session.getBasicRemote().sendText(message);
    }

    private String getClientIpAddress(Session session) {
        String resultIp = "";
        return resultIp;
    }

}
